// 获取系统信息（如进程、CPU、磁盘、组件温度和网络）的库 https://crates.io/crates/sysinfo
/*
它目前支持以下操作系统（按字母顺序排列）：
    Android
    FreeBSD
    iOS
    Linux
    macOS
    Raspberry Pi
    Windows
你仍然可以在不支持的操作系统上使用 sysinfo，但它什么也不会做，而且总是返回空值。你可以通过检查 [IS_SUPPORTED_SYSTEM] 常量，直接在程序中检查操作系统是否受支持。
rustc 支持的最低版本是 1.74。
*/
use sysinfo::{Components, CpuRefreshKind, Disks, Networks, RefreshKind, System, Users};

fn main() {
    // 请注意，我们使用“new_all”来确保所有列表
    // CPU 和进程已满！
    let mut sys = System::new_all();

    // 首先，我们更新“系统”结构的所有信息。
    sys.refresh_all();

    println!("=====> 系统信息:");
    // 显示系统信息：
    println!("系统名称:             {:?}", System::name().unwrap());
    println!("系统内核版本:          {:?}", System::kernel_version().unwrap());
    println!("系统操作系统版本:       {:?}", System::os_version().unwrap());
    println!("系统主机名:            {:?}", System::host_name().unwrap());


    println!("=====> 系统内存信息:");
    // RAM和交换信息：    大家可以使用 free -h 命令查看系统内存使用情况信息
    println!("总内存:        {} MB", sys.total_memory() / 1024 / 1024); // 显示总内存,单位为MB.总内存等于 已用内存 + 可用内存
    println!("已用内存 :     {} MB", sys.used_memory() / 1024 / 1024);  // 显示已用内存
    println!("可用内存 :     {} MB", sys.available_memory() / 1024 / 1024); // 显示可用内存
    println!("可用内存 :     {} MB", sys.free_memory() / 1024 / 1024);  // 显示空闲内存
    println!("total swap  : {} bytes", sys.total_swap());   // 显示总交换空间
    println!("used swap   : {} bytes", sys.used_swap());     // 显示已用交换空间

    // 显示进程 ID、名称 和 磁盘使用情况：
    // for (pid, process) in sys.processes() {
    //     println!("[{pid}] {:?} {:?}", process.name(), process.disk_usage());
    // }

    // 我们显示所有磁盘的信息：
    println!("=====> 系统磁盘信息:");
    let disks = Disks::new_with_refreshed_list();
    for disk in &disks {
        println!("{disk:?}");
    }

    // 网络接口名称、接收的数据总数和传输的数据总数：
    let networks = Networks::new_with_refreshed_list();
    println!("=====> 系统网络接口信息:");
    for (interface_name, data) in &networks {
        println!(
            "{interface_name}: {} B (down) / {} B (up)",
            data.total_received(),
            data.total_transmitted(),
        );
        // 如果您想要自上次调用以来接收/传输的数据量
        // 到“Networks：：refresh”，请使用“received”/“transmitted”。
    }

    // 组件温度：
    let components = Components::new_with_refreshed_list();
    println!("=====> 系统元件温度信息:");
    for component in &components {
        println!("{component:?}");
    }

    println!("=====> 系统CPU信息:");
    // CPU 数量：
    println!("CPU 总核心数量: {}", sys.cpus().len());
    // 推荐使用一个定时器来刷新并获取最新系统信息。
    // 请记住，要获得一些最新信息，您需要调用相应的刷新方法。例如，CPU 使用率：
    // 每次获取 CPU 实时信息时，都需要调用“refresh_cpu_usage”。例如： CPU 总使用率、每个 CPU 的使用率、全局 CPU 使用率。
    for _ in 0..2 {
        // 创建一个新的 System 实例并刷新与给定 RefreshKind 对应的数据。
        let mut system = System::new_with_specifics(
            // 刷新CPU的一切信息，包括每个CPU的使用率。频率等等
            RefreshKind::new().with_cpu(CpuRefreshKind::everything()),
        );
        // 请稍等片刻，因为 CPU 使用率基于 diff。
        // 休眠，让系统有时间长时间运行，以足以获得有用的信息。
        std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
        // 再次刷新 CPU 以获得实际值。先CPU总刷新，在当需要CPU使用率时再刷新使用率。需要CPU频率时刷新频率等
        system.refresh_cpu_usage();
        println!("CPU 总体使用率: {}%", system.global_cpu_usage()); // 显示全局 CPU 使用率。
        for (i, cpu) in system.cpus().iter().enumerate() {
            println!("CPU #{}: {}%", i, cpu.cpu_usage());
        }

        // 休眠一段时间，然后再次获取CPU信息。
        std::thread::sleep(std::time::Duration::from_secs(2));
    }

    // 良好实践/性能优化建议：
    // 1、大多数情况下，你不需要 sysinfo 提供的所有信息，而只需要其中的一个子集。在这种情况下，建议使用 refresh_specifics(...)方法，只获取所需的信息，这样性能会更好。
    // 2、另一个经常遇到的问题是：除非你知道自己在做什么，否则几乎所有时候都最好一次实例化 System 结构，并在程序中使用这个实例。这是因为很多信息都需要事先计算（例如 CPU 使用率）。
    // 另一个更好的例子是：如果要列出所有正在运行的进程，sysinfo 需要为 Process 结构列表分配全部内存，这在第一次运行时需要花费不少时间。
    // 3、如果您的程序需要使用大量文件描述符，最好使用 sysinfo::set_open_files_limit(0); 方法限制系统打开的文件描述符数量。
    // 这是因为 sysinfo 会打开大量文件描述符，以便在刷新进程时在某些目标上获得更好的性能。


    println!("=====> 系统lcqh用户信息:");
    // 显示用户信息：
    let users = Users::new_with_refreshed_list();
    let user = users.list().iter().find(|user| user.name() == "lcqh").unwrap();
    println!("{:?}", user);
    println!("{}", *user.group_id());
    println!("{:?}", *user.id());
    println!("{}", user.name());
    println!("{} is in {:?}", user.name(), user.groups());
}
